package com.sca4cloud.sca.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.google.code.kaptcha.Producer;
import com.sca4cloud.sca.common.core.constant.CacheConstants;
import com.sca4cloud.sca.common.core.constant.CommonConstants;
import com.sca4cloud.sca.common.core.constant.SecurityConstants;
import com.sca4cloud.sca.common.core.exception.ValidateCodeException;
import com.sca4cloud.sca.common.core.util.R;
import com.sca4cloud.sca.common.core.util.SpringContextHolder;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;

/**
 * 前端调用的验证码生成、验证接口 兼容vue+bootstrap两个前端框架
 */
@RestController
public class SbaCaptchaController {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "captchaProducer")
    private Producer captchaProducer;

    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

    /**
     * 验证码
     */
    @GetMapping("/captcha")
    public String kaptcha(HttpServletRequest request) throws Exception {
        String type = request.getParameter("type");
        String randomStr = request.getParameter("randomStr");
        String capStr = null;
        String code = null;
        BufferedImage bi = null;
        if ("math".equals(type)) {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            bi = captchaProducerMath.createImage(capStr);
        } else if ("char".equals(type)) {
            capStr = code = captchaProducer.createText();
            bi = captchaProducer.createImage(capStr);
        }

        // 保存验证码信息
        String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
        redisTemplate.opsForValue().set(key, code, SecurityConstants.CODE_TIME, TimeUnit.SECONDS);

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ImageIO.write(bi, "jpg", stream);
        return "data:image/jpg;base64," + Base64.encode(stream.toByteArray()).replaceAll("\r\n", "");

    }

    // 检查验证码是否正确
    @PostMapping(value = "/checkCode")
    @SneakyThrows
    public String checkCode(HttpServletRequest request) {
        String curCode = request.getParameter("code");
        if (StrUtil.isBlank(curCode))
            throw new ValidateCodeException("验证码不能为空");
        String randomStr = request.getParameter("randomStr");
        if (StrUtil.isBlank(randomStr))
            throw new ValidateCodeException("随机值不能为空");
        String result = "true";
        // 验证码校验
        String key = CacheConstants.DEFAULT_CODE_KEY + randomStr;
        Object codeObj = redisTemplate.opsForValue().get(key);
        if (codeObj == null || (!curCode.equalsIgnoreCase(codeObj.toString()))) {
            result = "false";
        }
        return result;
    }

    /**
     * vue前端的验证码
     */
    @GetMapping("/code")
    public R code(HttpServletRequest request) throws Exception {
        CaptchaVO vo = new CaptchaVO();
        vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
        CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
        ResponseModel responseModel = captchaService.get(vo);
        return R.ok(responseModel);
    }

    // vue前端的检查验证码是否正确
    @PostMapping(value = "/code/check")
    @SneakyThrows
    public R checkVueCode(HttpServletRequest request) {
        CaptchaVO vo = new CaptchaVO();
        vo.setPointJson(request.getParameter("pointJson"));
        vo.setToken(request.getParameter("token"));
        vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);

        CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
        ResponseModel responseModel = captchaService.check(vo);
        return R.ok(responseModel);
    }
}